/*
Copyright [2012] [Maria Eugenia Malagamba]
Copyright [2012] [Leandro Pellegrino]
Copyright [2012] [Julia Gambuzzi]
Copyright [2012] [Ignacio Capodanno]

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
*/

#include "Tablero.h"

using namespace Entidades;
using namespace Parser;

Tablero::Tablero(string pathXML, string pathCarpetaCliente, string nombreCliente, string nombreOtroCliente, bool levantarUnaPantalla, 
				 int numeroNave, int numeroNaveDelOtroCliente){

	this->log = Log::getInstanciaEventos();
	this->log->escribir("==================================");
	this->log->escribir("   Logs eventos ASTEROIDS");
	this->log->escribir("==================================");
	this->hidratador = new Hidratador(pathXML,pathCarpetaCliente);
	this->alto = hidratador->getAltoTablero();
	this->ancho = hidratador->getAnchoTablero();
	this->valoresParametrizables = new ValoresParametrizablesBonus();
	this->fondo = SDL_LoadBMP(hidratador->getNombreFondo().c_str());
	this->tiposAsteroides = this->hidratador->hidratarTiposDeAsteroide();
	
	// hidratamos las naves
	if (numeroNave > 0)
		this->nave = this->hidratador->hidratarNave(numeroNave);
	else
		this->nave = this->hidratador->hidratarNave();
	
	if (numeroNaveDelOtroCliente > 0)
		this->naveOtroCliente = this->hidratador->hidratarNave(numeroNaveDelOtroCliente);
	else
		this->naveOtroCliente = this->hidratador->hidratarNave();

	this->asteroides = this->hidratador->hidratarAsteroides();
	this->armarBackupAsteroides();
	
	this->armas = new vector<Arma*>;
	this->armasOtroCliente = new vector<Arma*>;

	this->bonus = new vector<GeneradorBonus*>();

	this->jugadorUno = new Jugador(this->nave, this->ancho, this->alto, nombreCliente, numeroNave, 1 );
	this->jugadorDos = new Jugador(this->naveOtroCliente, this->ancho, this->alto, nombreOtroCliente, numeroNaveDelOtroCliente, 2 );

	this->timer = new Timer();
	this->timer->tiempoDesdeUltimoFrame();

	if (levantarUnaPantalla){
		// Establecemos el modo de video
		this->pantalla = SDL_SetVideoMode(this->ancho, this->alto, 24, SDL_HWSURFACE|SDL_DOUBLEBUF);
		if(this->pantalla == NULL) {
			// error
		}
		SDL_WM_SetCaption("Asteroids",NULL);
		SDL_WM_SetIcon(SDL_LoadBMP("icono.bmp"), NULL);
	}
}

void Tablero::armarBackupAsteroides(){

	this->bakcup_asteroides = new vector<Asteroide*>(); 
	bool espar = false;
	for(unsigned int i = 0; i < this->getAsteroides()->size();i++){
		Asteroide* asteroideOld = this->getAsteroides()->at(i);
		Asteroide* asteroide = new Asteroide(asteroideOld->getDireccionActual(),asteroideOld->getVelocidad()*15, 
			asteroideOld->getTipoDeAsteroide(), asteroideOld->getPosicionX(), asteroideOld->getPosicionY(),
			asteroideOld->getPathDeLaImagen(), asteroideOld->getAnchoDeLaImagen(), asteroideOld->getAltoDeLaImagen(), 
			asteroideOld->getRotacionDeLaImagen());
		if(espar){
			asteroide->setPosicionX(1-asteroideOld->getAnchoDeLaImagen());
		}else{
			asteroide->setPosicionY(1-asteroideOld->getAltoDeLaImagen());
		}
		this->bakcup_asteroides->push_back(asteroide);
		espar = !espar;
	}
}

void Tablero::inicio(){

	
}


void Tablero::juego(){

	
}

void Tablero::actualizarPantalla(){
		Uint32 negro = SDL_MapRGB(this->pantalla->format,0,0,0);
		SDL_FillRect(this->pantalla, NULL, negro);
		SDL_Flip(pantalla); 

}

//Se encarga de mantener a los objetos en posiciones dentro de la pantalla
void Tablero::mantenerPintableDentro(Pintable* pintable){

	if (pintable->getPosicionY() + pintable->getAltoDeLaImagen() <=0){
		double cachitoY = (-1)* pintable->getPosicionY() - pintable->getAltoDeLaImagen();
		pintable->setPosicionY(this->alto - cachitoY);
	}
	if (pintable->getPosicionY() >= this->alto){
		pintable->setPosicionY(pintable->getPosicionY() - this->alto - pintable->getAltoDeLaImagen());
	}
	if (pintable->getPosicionX() + pintable->getAnchoDeLaImagen() <=0){
		double cachitoX = (-1)* pintable->getPosicionX() - pintable->getAnchoDeLaImagen();
		pintable->setPosicionX( this->ancho - cachitoX );
	}
	if (pintable->getPosicionX() >= this->ancho){
		pintable->setPosicionX(pintable->getPosicionX() - this->ancho - pintable->getAnchoDeLaImagen());
	}
}

/* Valida que la nave este en una posicion donde no choque con ningun asteroide
ni con la otra nave ni con una base*/
bool Tablero::esPosicionInicialNaveValida(Nave* nave, Nave* otraNave){

	//bool esValida = true;
	int anchoImagenNave = nave->getAnchoDeLaImagen();
	int altoImagenNave = nave->getAltoDeLaImagen();
	int navePosicionX = nave->getPosicionX();
	int navePosiocionY = nave->getPosicionY();

	for (unsigned int i = 0; i < this->asteroides->size(); i++){
		int posicionAsteroideEjeX = this->asteroides->at(i)->getPosicionX();
		int anchoImagenAsteroide = this->asteroides->at(i)->getAnchoDeLaImagen();
		int posicionAsteroideEjeY = this->asteroides->at(i)->getPosicionY();
		int altoImagenAsteroide = this->asteroides->at(i)->getAltoDeLaImagen();

		bool condicionUno = nave->getPosicionX() + anchoImagenNave >= posicionAsteroideEjeX;
		bool condicionDos = nave->getPosicionX() <= posicionAsteroideEjeX + anchoImagenAsteroide;
		bool condicionTres = nave->getPosicionY() <= posicionAsteroideEjeY + altoImagenAsteroide;
		bool condicionCuatro = nave->getPosicionY() + altoImagenNave >= posicionAsteroideEjeY;

		if ((condicionUno && condicionDos) && (condicionTres && condicionCuatro)) {
			return false;
		}
	}
	
	//Posicion de la Base1
	int posicionBaseEjeX = this->getJugadorUno()->getBase()->getPosicionX();	
	int posicionBaseEjeY = this->getJugadorUno()->getBase()->getPosicionY();
	int anchoBase = this->getJugadorUno()->getBase()->getAnchoDeLaImagen();
	int altoBase = this->getJugadorUno()->getBase()->getAltoDeLaImagen();

	//Posicion de la Base2
	int posicionBaseOtroClienteEjeX = this->getJugadorDos()->getBase()->getPosicionX();
	int posicionBaseOtroClienteEjeY = this->getJugadorDos()->getBase()->getPosicionY();
	int anchoBaseOtroCliente = this->getJugadorDos()->getBase()->getAnchoDeLaImagen();
	int altoBaseOtroCliente = this->getJugadorDos()->getBase()->getAltoDeLaImagen();

	//chequeo que no colicione con las bases
	Rectangulo* baseCliente = new Rectangulo(posicionBaseEjeX,posicionBaseEjeY,anchoBase,altoBase);
	Rectangulo* baseOtroCliente = new Rectangulo(posicionBaseOtroClienteEjeX,posicionBaseOtroClienteEjeY,anchoBaseOtroCliente,altoBaseOtroCliente);
	Rectangulo* naveRec = new Rectangulo(navePosicionX,navePosiocionY,anchoImagenNave,altoImagenNave);

	bool condicion1 = baseCliente->hayIntereseccion(naveRec);
	bool condicion2 = baseOtroCliente->hayIntereseccion(naveRec);
	
	//Borramos los Rectangulos ;-)
	delete baseCliente;
	delete baseOtroCliente;
	delete naveRec;

	if (condicion1){
		return false;
	}
	if (condicion2){
		return false;
	}

	//chequeo que no colisione con la otra nave
	int posicionOtraNaveEjeX = otraNave->getPosicionX();
	int anchoImagenOtraNave = otraNave->getAnchoDeLaImagen();
	int posicionOtraNaveEjeY = otraNave->getPosicionY();
	int altoImagenOtraNave = otraNave->getAltoDeLaImagen();

	bool condicionUno = nave->getPosicionX() + anchoImagenNave >= posicionOtraNaveEjeX;
	bool condicionDos = nave->getPosicionX() <= posicionOtraNaveEjeX + anchoImagenOtraNave;
	bool condicionTres = nave->getPosicionY() <= posicionOtraNaveEjeY + altoImagenOtraNave;
	bool condicionCuatro = nave->getPosicionY() + altoImagenNave >= posicionOtraNaveEjeY;

	if ((condicionUno && condicionDos) && (condicionTres && condicionCuatro)) {
		return false;
	}
	return true;
}

void Tablero::posicionarNave(Nave* nave1, Nave* nave2){
	
	srand(time(NULL));
	//Se ubica a la nave1 dentro de la pantalla
	int contador = 0;
	while (!esPosicionInicialNaveValida(nave1, nave2) && contador != 20000) {
		contador ++;
		int alto = this->alto;
		int ancho = this->ancho;
		int x = rand()%(ancho - nave->getAnchoDeLaImagen()+ 1);
		int y = rand()%(alto - nave->getAltoDeLaImagen() + 1);
		nave1->setPosicionX(x);
		nave1->setPosicionY(y);
		
	}
}

SDL_Surface* Tablero::getPantalla(){
	return this->pantalla;
}

SDL_Surface* Tablero::getFondo(){
	return this->fondo;
}


double Tablero::getAlto(){
 return this->alto;
}

double Tablero::getAncho(){
 return this->ancho;
}

Nave* Tablero::getNave(){
	return this->nave;
}

vector<Asteroide*>* Tablero::getAsteroides(){
	return this->asteroides;
}

vector<Asteroide*>* Tablero::getBackupAsteroides(){
	return this->bakcup_asteroides;
}

Nave* Tablero::getNaveOtroCliente(){
 return this->naveOtroCliente;
}

vector<Arma*>* Tablero::getArmas(){
	return this->armas;
}

vector<Arma*>* Tablero::getArmasOtroCliente(){
	return this->armasOtroCliente;
}


Jugador* Tablero::getJugadorUno(){
	return this->jugadorUno;
}

Jugador* Tablero::getJugadorDos(){
	return this->jugadorDos;
}

Timer* Tablero::getTimer(){
	return this->timer;
}

vector<GeneradorBonus*>* Tablero::getBonus(){
	return this->bonus;
}


vector<TipoDeAsteroide>* Tablero::getTiposAsteroides(){
	return this->tiposAsteroides;
}

int Tablero::getPosicionTipoDeAsteroide(string tipoDeAsteroide){

	for (unsigned int i = 0; i < this->tiposAsteroides->size(); i++){
		if (this->tiposAsteroides->at(i).nombre == tipoDeAsteroide) return i;
	}
	//no encontre el tipo de asteroide en el vector porque no estaba en el XML.
	return -1;
}


Tablero::~Tablero(void)
{
	for(unsigned int i = 0; i < this->asteroides->size(); i++){
		delete (this->asteroides->at(i));
	}
	delete this->asteroides;

	for(unsigned int i = 0; i < this->bakcup_asteroides->size(); i++){
		delete (this->bakcup_asteroides->at(i));
	}
	delete this->bakcup_asteroides;

	if (this->nave != NULL)
	{
		delete this->nave;
	}

	delete this->hidratador;

	SDL_FreeSurface(this->fondo);

}

